
#include <stdio.h>
#include <BDrag>
#include <BOpenGL>
#include <BPixmap>
#include <BKeyEvent>
#include <BMouseEvent>

#include "IGlobal.h"
#include "member_BWidget.h"
#include "member_BObject.h"
#include "member_BLayout.h"
#include "member_BStyle.h"
#include "member_BEvent.h"
#include "member_BEventFilter.h"

using namespace BWE;

extern BArray<GLuint>		UnusedTextureObjects;
extern BArray<GLuint>		UnusedFrameBufferObjects;
extern BArray<GLuint>		UnusedRenderBufferObjects;

member_BWidget::member_BWidget(BWidget* widget)
{
	boss = widget;
	window = 0;
	pixmap = 0;
	parent = 0;

	border = 1;
	perch = 0;
	margin = 1;
	sizePolicy = Policy_Preferred | Policy_Dynamic;
	size.set(100, 100);
	minSize.set(0, 0);
	maxSize.set(999999, 999999);

	frameless = false;
	visible = true;
	refresh = true;
	modal = false;
	focusable = true;
	focused = false;
	floating = true;
	droppable = false;
	dirtyStyle = true;
	upperLayout = 0;

	dirty = true;
	opacity = 255;
	layered = false;
	samples = 4;
	resized = true;
	fbo = 0;
	tbo = 0;

	freshRects();
}
member_BWidget::~member_BWidget()
{
	if (tbo)
		UnusedTextureObjects.append(tbo);
	if (fbo)
		UnusedFrameBufferObjects.append(fbo);
}

bool member_BWidget::ignored() const
{
	if (upperLayout)
	{
		const BRect& rect = upperLayout->area(boss);
		if (rect.empty())
			return true;
		BLayout* layout = upperLayout;
		while (layout)
		{
			if (!layout_member(layout)->visible)
				return true;
			layout = layout_member(layout)->parent;
		}
	}
	return false;
}
void member_BWidget::freshEnabled(bool enabled)
{
	boss->fresh();
	state.enabled = enabled;
	if (state.enabled)
	{
		state.enabled = object_member(boss)->enabled;
	}
	else
	{
		if (focused)
			boss->setFocused(false);
		if (state.hovered)
			state.hovered = false;
	}
	if (state.enabled)
	{
		BLayout* layout = upperLayout;
		while (layout)
		{
			if (!object_member(layout)->enabled)
			{
				state.enabled = false;
				break;
			}
			layout = layout_member(layout)->parent;
		}
	}
	for (int i = 0; i < children.size(); i++)
	{
		BWidget* child = children[i];
		widget_member(child)->freshEnabled(state.enabled);
	}
}

void member_BWidget::clearLayer()
{
	for (int i = 0; i < children.size(); i++)
	{
		BWidget* child = children[i];
		widget_member(child)->clearLayer();
	}
	if (tbo)
	{
		UnusedTextureObjects.append(tbo);
		tbo = 0;
	}
	if (fbo)
	{
		UnusedFrameBufferObjects.append(fbo);
		fbo = 0;
	}
	resized = false;
}
void member_BWidget::frame(GLuint msfbo, GLenum mode)
{
	if (fbo == 0 || tbo == 0)
		resized = true;
	if (resized)
	{
		GLint backup_frame_buffer;
		glGetIntegerv(GL_FRAMEBUFFER_BINDING, &backup_frame_buffer);
		if (!fbo)
		{
			glGenFramebuffers(1, &fbo);
		}
		if (fbo)
		{
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
		}
		if (!tbo)
		{
			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
			glGenTextures(1, &tbo);
		}
		if (tbo)
		{
			glBindTexture(GL_TEXTURE_2D, tbo);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
			glBindTexture(GL_TEXTURE_2D, 0);
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tbo, 0);
		}
		glBindFramebuffer(GL_FRAMEBUFFER, backup_frame_buffer);
		resized = false;
	}
	if (fbo)
	{
		GLint backup_frame_buffer;
		glGetIntegerv(GL_FRAMEBUFFER_BINDING, &backup_frame_buffer);

		if (msfbo > 0)
		{
			glBindFramebuffer(GL_FRAMEBUFFER, msfbo);
			glDrawBuffer(mode);
			glReadBuffer(mode);
		}
		else
		{
			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
			glDrawBuffer(GL_COLOR_ATTACHMENT0);
			glReadBuffer(GL_COLOR_ATTACHMENT0);
		}

		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		glDisable(GL_LIGHTING);
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_CULL_FACE);
		glDisable(GL_MULTISAMPLE);

		glEnable(GL_BLEND);
		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
		glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
		glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);

		glViewport(0, 0, size.width(), size.height());

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0, size.width(), size.height(), 0, -1, 1);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		if (realStyle)
		{
			state.style = realStyle;
			state.font = realStyle->font();
		}
		else
		{
			state.style = app_style;
			state.font = app_style->font();
		}

		state.paint = Paint_All;
		event.reset(Event_Paint);
		event.setValue(BValue());
		boss->emit(Signal_Paint, event.value());
		if (event.value().is<int>())
			state.paint -= (int)event.value();
		if (event.value().is<Paint>())
			state.paint -= (Paint)event.value();
		if (event.value().is<PaintFlag>())
			state.paint -= (PaintFlag)event.value();
		this->procEvent(event);

		dirty = false;
		if (layered)
		{
			glEnable(GL_TEXTURE_2D);
			for (int i = 0; i < children.size(); i++)
			{
				BWidget* child = children[i];
				if (!widget_member(child)->visible)
					continue;
				if (widget_member(child)->ignored())
					continue;
				if (widget_member(child)->floating)
					drawWidget(child, size, child->pos(), size.height());
				else
					drawWidget(child, rectCenter, child->pos(), size.height());
			}
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
		}

		if (msfbo > 0)
		{
			glBindFramebuffer(GL_READ_FRAMEBUFFER, msfbo);
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
			glBlitFramebuffer(0, 0, size.width(), size.height(), 0, 0, size.width(), size.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
		}

		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
		glDrawBuffer(GL_COLOR_ATTACHMENT0);
		glReadBuffer(GL_COLOR_ATTACHMENT0);

		boss->emit(Signal_Framed);

		glBindFramebuffer(GL_FRAMEBUFFER, backup_frame_buffer);
	}
}
void member_BWidget::drawWidget(BWidget* widget, const BRect& clip, const BPoint& offset, int frameHeight)
{
	if (!widget_member(widget)->visible)
		return;
	BSize size = widget->size();
	BRect ab_rect(offset, size);
	BRect view = ab_rect & clip;
	if (view.empty())
		return;

	glViewport(view.x(), frameHeight - view.bottom(), view.width(), view.height());

	BRect area(view.pos() - ab_rect.pos(), view.size());
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(area.left(), area.right(), area.bottom(), area.top(), -1, 1);

	if (widget_member(widget)->tbo)
	{
		int width = widget_member(widget)->size.width();
		int height = widget_member(widget)->size.height();
		glColor4ub(255, 255, 255, widget_member(widget)->opacity);
		glBindTexture(GL_TEXTURE_2D, widget_member(widget)->tbo);
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f, 1.0f);		glVertex2i(0, 0);
		glTexCoord2f(0.0f, 0.0f);		glVertex2i(0, height);
		glTexCoord2f(1.0f, 0.0f);		glVertex2i(width, height);
		glTexCoord2f(1.0f, 1.0f);		glVertex2i(width, 0);
		glEnd();
	}
	if (!widget_member(widget)->layered)
	{
		BRect ab_crect = rectCenter + offset;
		BRect cview = ab_crect & clip;
		BWidgetHolderArray& children = widget_member(widget)->children;
		for (int i = 0; i < children.size(); i++)
		{
			BWidget* child = children[i];
			if (!widget_member(child)->visible)
				continue;
			if (widget_member(child)->ignored())
				continue;
			if (widget_member(child)->floating)
				drawWidget(child, view, offset + child->pos(), frameHeight);
			else
				drawWidget(child, cview, offset + child->pos(), frameHeight);
		}
	}
}
void member_BWidget::takeLayout(BLayout* layout)
{
	for (int i = 0; i < layout->count(); i++)
	{
		if (BWidget* child = layout->widget(i))
		{
			BHolder<BWidget> holder(child);
			widget_member(child)->parent = 0;
			BWidget* root = boss->root();
			if (widget_member(root)->window)
			{
				widget_member(root)->window->popup(child, false);
				//widget_member(child)->clearLayer();
			}
			if (widget_member(child)->visible && widget_member(child)->state.shown)
			{
				BEvent event(Event_Hide);
				widget_member(child)->procEvent(event);
			}
			children.remove(child);
			object_member(child)->emit(Signal_ParentChanged);
			boss->emit(Signal_Remove, BValue(child, this));
			continue;
		}
		if (BLayout* child = layout->layout(i))
		{
			takeLayout(child);
		}
	}
	layout_member(layout)->host = 0;
}

void member_BWidget::freshTitle()
{
	t_title.clear();
	if (title.size())
	{
		if (state.titleStyle)
			state.titleStyle->translate(title, t_title);
		if (t_title.empty() && realStyle)
			realStyle->translate(title, t_title);
	}
	if (window)
	{
		window->setWindowTitle(t_title.empty() ? title : t_title);
	}
}
void member_BWidget::syncWindowPos(const BPoint& wpos)
{
	if (pos != wpos)
	{
		pos = wpos;
		//BEvent moveEvent(Event_Move);
		//procEvent(moveEvent);
	}
}
void member_BWidget::syncWindowSize(const BSize& wsize)
{
	BSize temp = wsize;
	temp.limit(minSize, maxSize);
	if (size != temp)
	{
		size = temp;
		dirtyRects = true;
		freshRects();
		boss->adjust();
		BEvent resizeEvent(Event_Resize);
		procEvent(resizeEvent);
	}
}

void member_BWidget::procEvent(const BEvent& event)
{
	if (event_member(&event)->window == 0)
	{
		BWidget* root = boss->root();
		event_member(&event)->window = widget_member(root)->window;
	}
	Event type = event.type();
	switch (type)
	{
	case Event_Show:
		state.shown = true;
		freshLayoutPerch();
		if (dirtyRects)
		{
			freshRects();
			dirtyLayout();
			BEvent resizeEvent(Event_Resize);
			resizeEvent.setValue(size);
			procEvent(resizeEvent);
		}
		dirtyPixmaps();
		break;
	case Event_Hide:
		dirtyPixmaps();
		break;
	case Event_Move:
		dirtyPixmaps();
		break;
	case Event_Resize:
		boss->fresh();
		dirtyPixmaps();
		break;
	case Event_Adjust:
		boss->fresh();
		break;
	case Event_Active:
		boss->fresh();
		break;
	case Event_Style:
		if (realStyle)
		{
			applyStyle();
		}
		if (dirtyRects)
		{
			freshRects();
			dirtyLayout();
			BEvent resizeEvent(Event_Resize);
			resizeEvent.setValue(size);
			procEvent(resizeEvent);
		}
		dirtyPixmaps();
		dirtyUpperLayout();
		boss->fresh();
		break;
	case Event_Fresh:
		if (dirtyStyle)
		{
			dirtyStyle = false;
			BEvent styleEvent(Event_Style);
			dispenseStyles(styleEvent);
		}
		freshLayoutPerch();
		if (dirtyRects)
		{
			freshRects();
			dirtyLayout();
			BEvent resizeEvent(Event_Resize);
			resizeEvent.setValue(size);
			procEvent(resizeEvent);
		}
		if (visible && !state.shown)
		{
			state.shown = true;
			BEvent showEvent(Event_Show);
			procEvent(showEvent);
		}
		break;
	default:
		break;
	}
	if (type == Event_Paint)
	{
		boss->event(event);
		for (int i = 0; i < layouts.size(); i++)
		{
			BLayout* layout = layouts[i];
			if (layout_member(layout)->visible)
				layout_member(layout)->dispenseEvent(event);
		}
		if (BEventFilter* filter = eventFilter)
		{
			if (object_member(filter)->enabled)
				filter_member(filter)->dispenseEvent(event);
		}
	}
	else
	{
		if (eventFilter && eventFilter->enabled())
		{
			filter_member(eventFilter)->dispenseEvent(event);
			if (event.accepted())
				return;
		}
		if (type >= Event_Active && type <= Event_DoubleClick)
		{
			for (int i = 0; i < layouts.size(); i++)
			{
				BLayout* layout = layouts[i];
				if (layout->enabled())
					layout_member(layout)->dispenseEvent(event);
				if (event.accepted())
					return;
			}
		}
		if (!event.accepted())
		{
			boss->event(event);
		}
	}
}

void member_BWidget::dispenseUpperStyles(BWidget* upper)
{
	if (BWidget* parent = widget_member(upper)->parent)
	{
		dispenseUpperStyles(parent);
	}
	if (BStyle* style = widget_member(upper)->realStyle)
	{
		style_member(style)->apply(boss, parent == upper);
	}
}
void member_BWidget::dispenseUpperStyles(BLayout* layout)
{
	if (BLayout* parent = layout_member(layout)->parent)
	{
		dispenseUpperStyles(parent);
	}
	if (BStyle* style = layout_member(layout)->realStyle)
	{
		style_member(style)->apply(boss, upperLayout == layout);
	}
}
void member_BWidget::dispenseStyles(BEvent& event)
{
	if (realStyle)
	{
		realStyle->clearAll();
		realStyle->clearAnnexes();
		realStyle->clearChildren();
	}
	style_member(app_style)->apply(boss, true);
	if (parent)
		dispenseUpperStyles(parent);
	if (upperLayout)
		dispenseUpperStyles(upperLayout);
	if (style)
	{
		if (realStyle.empty())
			realStyle = new BStyle();
		style_member(realStyle)->overlap(style);
		style_member(style)->apply(boss, false);
	}
	if (realStyle)
	{
		for (int i = 0; i < layouts.size(); i++)
		{
			BLayout* layout = layouts[i];
			layout_member(layout)->dispenseStyles(realStyle, event);
		}
	}
	for (int i = 0; i < children.size(); i++)
	{
		BWidget* child = children[i];
		widget_member(child)->dispenseStyles(event);
		widget_member(child)->dirtyStyle = false;
	}
	if (realStyle)
	{
		event.setValue(realStyle);
		this->procEvent(event);
	}
	else
	{
		event.setValue(app_style);
		this->procEvent(event);
	}
}
void member_BWidget::applyStyle()
{
	if (const BStyle* style = realStyle)
	{
		if (style_member(style)->assign(Value_FrameLess, frameless))
		{
			if (window)
				window->setFrameless(frameless);
		}
		if (style_member(style)->assign(Value_Samples, samples))
		{
			if (window)
				window->resized = true;
		}
		style_member(style)->assign(Value_Tips, tips);
		style_member(style)->assign(Value_Border, border);

		style_member(style)->assign(Value_Perch_Left, perch.left());
		style_member(style)->assign(Value_Perch_Right, perch.right());
		style_member(style)->assign(Value_Perch_Top, perch.top());
		style_member(style)->assign(Value_Perch_Bottom, perch.bottom());

		style_member(style)->assign(Value_Margin_Left, margin.left());
		style_member(style)->assign(Value_Margin_Top, margin.top());
		style_member(style)->assign(Value_Margin_Right, margin.right());
		style_member(style)->assign(Value_Margin_Bottom, margin.bottom());

		style_member(style)->assign(Value_Min_Width, minSize.width());
		style_member(style)->assign(Value_Min_Height, minSize.height());
		style_member(style)->assign(Value_Max_Width, maxSize.width());
		style_member(style)->assign(Value_Max_Height, maxSize.height());

		style_member(style)->assign(Value_Width_Policy, sizePolicy.widthPolicy());
		style_member(style)->assign(Value_Height_Policy, sizePolicy.heightPolicy());

		if (style_member(style)->assign(Value_Fixed_Width, fixedSize.width()))
			sizePolicy.widthPolicy() = Policy_Fixed;
		if (style_member(style)->assign(Value_Fixed_Height, fixedSize.height()))
			sizePolicy.heightPolicy() = Policy_Fixed;

		style_member(style)->assign(Value_Width, size.width());
		style_member(style)->assign(Value_Height, size.height());
		if (window && window->getWindowSize() != size)
		{
			window->setWindowSize(size);
		}

		style_member(style)->assign(Value_Radius_Left_Top, radiusLeftTop);
		style_member(style)->assign(Value_Radius_Right_Top, radiusRightTop);
		style_member(style)->assign(Value_Radius_Left_Bottom, radiusLeftBottom);
		style_member(style)->assign(Value_Radius_Right_Bottom, radiusRightBottom);

		bool titleChanged = style_member(style)->assign(Value_Title, title);
		bool iconChanged = style_member(style)->assign(Value_Icon, icon);

		state.titleStyle = realStyle->annex("title");
		if (const BStyle* titleStyle = state.titleStyle)
		{
			if (style_member(titleStyle)->assign(Value_Text, title))
				titleChanged = true;
			if (style_member(titleStyle)->assign(Value_Icon, icon))
				iconChanged = true;
			style_member(titleStyle)->assign(Value_Margin_Left, state.titleMargin.left());
			style_member(titleStyle)->assign(Value_Margin_Top, state.titleMargin.top());
			style_member(titleStyle)->assign(Value_Margin_Right, state.titleMargin.right());
			style_member(titleStyle)->assign(Value_Margin_Bottom, state.titleMargin.bottom());
		}
		else
		{
			state.titleMargin.reset();
		}

		if (titleChanged && window)
		{
			window->setWindowTitle(title);
		}
		if (iconChanged && window)
		{
			window->setWindowIcon(icon);
		}

		this->freshTitle();
		boss->setSize(size);
		dirtyRects = true;
	}
}

void member_BWidget::dirtyPixmaps()
{
	if (pixmap)
		pixmap->dirty();
	BWidget* widget = parent;
	while (widget)
	{
		if (BPixmap* pixmap = widget_member(widget)->pixmap)
			pixmap->dirty();
		widget = widget_member(widget)->parent;
	}
}
void member_BWidget::freshRects()
{
	int b = border;
	int width = size.width();
	int height = size.height();

	int pleft = perch.left();
	int pright = perch.right();
	int ptop = perch.top();
	int pbottom = perch.bottom();

	int mleft = margin.left();
	int mright = margin.right();
	int mtop = margin.top();
	int mbottom = margin.bottom();

	int cx = b + pleft + mleft;
	int cy = b + ptop + mtop;
	int cw = width - b - pleft - mleft - mright - pright - b;
	int ch = height - b - ptop - mtop - mbottom - pbottom - b;

	rectTitle.set(b, b, width - b - b, ptop);
	rectTop.set(b + pleft, b, width - b - pleft - b - pright, ptop);
	rectRight.set(width - b - pright, b + ptop, pright, height - b - b - ptop - pbottom);
	rectLeft.set(b, b + ptop, pleft, height - b - b - ptop - pbottom);
	rectBottom.set(b + pleft, height - b - pbottom, width - b - b - pleft - pright, pbottom);
	rectLeftTop.set(b, b, pleft, ptop);
	rectLeftBottom.set(b, height - b - pbottom, pleft, pbottom);
	rectRightTop.set(width - b - pright, b, pright, ptop);
	rectRightBottom.set(width - b - pright, height - b - pbottom, pright, pbottom);
	rectCenter.set(cx, cy, cw, ch);

	if (radiusLeftTop.empty() && radiusRightTop.empty() && radiusLeftBottom.empty() && radiusRightBottom.empty())
		round = 0;
	else if (round.empty())
		round = new IRound();
	if (round)
	{
		round->frameSize.set((float)width, (float)height);
		round->radiusLeftTop = radiusLeftTop;
		round->radiusRightTop = radiusRightTop;
		round->radiusLeftBottom = radiusLeftBottom;
		round->radiusRightBottom = radiusRightBottom;
		round->reset();

		BPointfArray& outerPoints = round->outerPoints;
		BPointfArray& innerPoints = round->innerPoints;

		BRectf outerRect(0, 0, width, height);
		round->createPoints(outerRect, outerPoints);

		BRectf innerRect = outerRect;
		innerRect.left() += border;
		innerRect.right() -= border;
		innerRect.top() += border;
		innerRect.bottom() -= border;

		round->createPoints(innerRect, innerPoints);
		round->createTriangles(outerPoints, innerPoints, round->borderPoints);

		round->backgroundPoints = innerPoints;
		round->backgroundPoints.prepend(rectCenter.center());

		outerPoints.reset();
		round->createLeftTopPoints(innerRect, outerPoints);
		round->createRightTopPoints(innerRect, outerPoints);
		outerPoints.prepend(BPointf((float)rectLeft.left(), (float)rectTop.bottom()));
		outerPoints.append(BPointf((float)rectRight.right(), (float)rectTop.bottom()));
		outerPoints.append(BPointf((float)rectLeft.left(), (float)rectTop.bottom()));
		round->createTriangles(outerPoints, rectTop.center(), round->titlePoints);

		innerRect.left() = (float)rectLeft.right();
		innerRect.top() = (float)rectTop.bottom();
		innerRect.right() = (float)rectRight.left();
		innerRect.bottom() = (float)rectBottom.top();

		outerPoints = innerPoints;
		if (innerRect.valid())
		{
			round->createPoints(innerRect, innerPoints);
			round->createTriangles(outerPoints, innerPoints, round->perchPoints);
		}
		else
		{
			round->createTriangles(outerPoints, rectTop.center(), round->perchPoints);
			round->createTriangles(outerPoints, rectTop.center(), round->titlePoints);
		}

		outerPoints = innerPoints;
		round->createPoints(rectCenter, innerPoints);
		round->createTriangles(outerPoints, innerPoints, round->marginPoints);

		round->centerPoints = innerPoints;
		round->centerPoints.prepend(rectCenter.center());
	}

	resized = true;
	dirtyRects = false;
}
void member_BWidget::freshLayoutPerch()
{
	BPerch tempPerch = perch;
	for (int i = 0; i < layouts.size(); i++)
	{
		BLayout* layout = layouts[i];
		if (layout_member(layout)->dirty && layout_member(layout)->visible)
		{
			BSize hsize = layout->preferSize();
			if (layout_member(layout)->part & Part_Title && perch.top() < hsize.height())
				tempPerch.top() = hsize.height();
			if (layout_member(layout)->part & Part_Top && perch.top() < hsize.height())
				tempPerch.top() = hsize.height();
			if (layout_member(layout)->part & Part_Left && perch.left() < hsize.width())
				tempPerch.left() = hsize.width();
			if (layout_member(layout)->part & Part_Right && perch.right() < hsize.width())
				tempPerch.right() = hsize.width();
			if (layout_member(layout)->part & Part_Bottom && perch.bottom() < hsize.height())
				tempPerch.bottom() = hsize.height();
		}
	}

	if (tempPerch != perch)
	{
		perch = tempPerch;
		dirtyRects = true;
	}
}
void member_BWidget::adjustDirtyLayouts()
{
	bool adjusted = false;
	for (int i = 0; i < layouts.size(); i++)
	{
		BLayout* layout = layouts[i];
		if (layout_member(layout)->visible)
		{
			if (layout_member(layout)->part == Part_Title)
				layout->setRect(rectTitle);
			else if (layout_member(layout)->part == Part_Top)
				layout->setRect(rectTop);
			else if (layout_member(layout)->part == Part_Left)
				layout->setRect(rectLeft);
			else if (layout_member(layout)->part == Part_Right)
				layout->setRect(rectRight);
			else if (layout_member(layout)->part == Part_Bottom)
				layout->setRect(rectBottom);
			else if (layout_member(layout)->part == Part_Center)
				layout->setRect(rectCenter);
			else if (layout_member(layout)->part == Part_LeftTop)
				layout->setRect(rectLeftTop);
			else if (layout_member(layout)->part == Part_LeftBottom)
				layout->setRect(rectLeftBottom);
			else if (layout_member(layout)->part == Part_RightTop)
				layout->setRect(rectRightTop);
			else if (layout_member(layout)->part == Part_RightBottom)
				layout->setRect(rectRightBottom);
			if (layout_member(layout)->dirty)
			{
				layout->adjust();
				adjusted = true;
			}
		}
	}
	if (adjusted)
	{
		BEvent adjustEvent(Event_Adjust);
		this->procEvent(adjustEvent);
	}
}

void member_BWidget::dirtyLayout()
{
	for (int i = 0; i < layouts.size(); i++)
	{
		BLayout* layout = layouts[i];
		layout_member(layout)->dirty = true;
		dirtyLayouts = true;
	}
}
void member_BWidget::dirtyUpperLayout()
{
	if (upperLayout)
	{
		upperLayout->dirty(boss);
		if (parent)
		{
			widget_member(parent)->dirtyUpperLayout();
		}
	}
}
